package spring.cloud.tasks.executor.name_space.executor.task.task_listener.task_statistics;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Setter
@Getter
public final class TaskStatistics {

    private static ConcurrentMap<String, AtomicInteger> executorIdAndTaskIdKeyToSuccessCountMap = new ConcurrentHashMap<>();

    private static ConcurrentMap<String, AtomicInteger> executorIdAndTaskIdKeyToFailureCountMap = new ConcurrentHashMap<>();
    //
    private static ConcurrentMap<String, AtomicInteger> executorIdAndTaskIdKeyToTotalCountDeltaMap = new ConcurrentHashMap<>();

    private static ConcurrentMap<String, AtomicInteger> executorIdAndTaskIdKeyToFailureCountDeltaMap = new ConcurrentHashMap<>();

    //
    private static String buildTaskIdAndExecutorIdKey(String taskId, String executorId) {//
        return executorId + "-" + taskId;//但是底层存的是executorId-taskId
    }

    private static void incrementProcessCount(final ConcurrentMap<String, AtomicInteger> processCountMap, final String taskIdAndExecutorIdKey) {
        processCountMap.putIfAbsent(taskIdAndExecutorIdKey, new AtomicInteger(0));
        processCountMap.get(taskIdAndExecutorIdKey).incrementAndGet();
    }

    private static void incrementProcessCount(final ConcurrentMap<String, AtomicInteger> processCountMap, final String taskIdAndExecutorIdKey, final int count) {
        processCountMap.putIfAbsent(taskIdAndExecutorIdKey, new AtomicInteger(0));
        processCountMap.get(taskIdAndExecutorIdKey).addAndGet(count);
    }


    //

    /**
     * 增加本任务服务器处理数据正确的数量.
     *
     * @param taskId       任务名称
     * @param executorId   executor名
     * @param successCount 处理数据正确的数量
     */
    public static synchronized void incrementProcessSuccessCount(final String taskId, final String executorId, final int successCount) {
        incrementProcessCount(executorIdAndTaskIdKeyToSuccessCountMap, buildTaskIdAndExecutorIdKey(taskId, executorId), successCount);
    }

    /**
     * 获取本任务服务器处理数据正确的数量.
     *
     * @param taskId     任务名称
     * @param executorId executor名
     * @return 本任务服务器处理数据正确的数量
     */
    public static int getProcessSuccessCount(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        return null == executorIdAndTaskIdKeyToSuccessCountMap.get(taskIdAndExecutorIdKey) ? 0 : executorIdAndTaskIdKeyToSuccessCountMap.get(taskIdAndExecutorIdKey).get();
    }

    /**
     * 增加本任务服务器处理数据错误的数量.
     *
     * @param taskId       任务名称
     * @param executorId   executor名
     * @param failureCount 处理数据错误的数量
     */
    public static void incrementProcessFailureCount(final String taskId, final String executorId, final int failureCount) {
        incrementProcessCount(executorIdAndTaskIdKeyToFailureCountMap, buildTaskIdAndExecutorIdKey(taskId, executorId), failureCount);
    }


    /**
     * 获取本任务服务器处理数据错误的数量.
     *
     * @param taskId     任务名称
     * @param executorId executor名
     * @return 本任务服务器处理数据错误的数量
     */
    public static int getProcessFailureCount(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        return null == executorIdAndTaskIdKeyToFailureCountMap.get(taskIdAndExecutorIdKey) ? 0 : executorIdAndTaskIdKeyToFailureCountMap.get(taskIdAndExecutorIdKey).get();
    }

    /**
     * 重置success/failure统计信息. analyse的totalCount和errorCount不清零。
     *
     * @param taskId     任务名称
     * @param executorId executor名
     */
    public static void resetSuccessFailureCount(final String executorId) {

    }

    public static void resetSuccessFailureCount(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        if (executorIdAndTaskIdKeyToSuccessCountMap.containsKey(taskIdAndExecutorIdKey)) {
            executorIdAndTaskIdKeyToSuccessCountMap.get(taskIdAndExecutorIdKey).set(0);
        }
        if (executorIdAndTaskIdKeyToFailureCountMap.containsKey(taskIdAndExecutorIdKey)) {
            executorIdAndTaskIdKeyToFailureCountMap.get(taskIdAndExecutorIdKey).set(0);
        }
    }

    //
    public static void initTotalCountDelta(final String taskId, final String executorId, final int processCount) {//
        executorIdAndTaskIdKeyToTotalCountDeltaMap.put(buildTaskIdAndExecutorIdKey(taskId, executorId), new AtomicInteger(processCount));
    }

    public static synchronized void increaseTotalCountDelta(final String taskId, final String executorId) {//
        incrementProcessCount(executorIdAndTaskIdKeyToTotalCountDeltaMap, buildTaskIdAndExecutorIdKey(taskId, executorId));
    }

    public static int getTotalCountDelta(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        return null == executorIdAndTaskIdKeyToTotalCountDeltaMap.get(taskIdAndExecutorIdKey) ? 0 : executorIdAndTaskIdKeyToTotalCountDeltaMap.get(taskIdAndExecutorIdKey).get();
    }

    //
    public static void initFailureCountDelta(final String taskId, final String executorId, final int errorCount) {//
        executorIdAndTaskIdKeyToFailureCountDeltaMap.put(buildTaskIdAndExecutorIdKey(taskId, executorId), new AtomicInteger(errorCount));
    }

    public static synchronized void increaseErrorCountDelta(final String taskId, final String executorId) {//
        incrementProcessCount(executorIdAndTaskIdKeyToFailureCountDeltaMap, buildTaskIdAndExecutorIdKey(taskId, executorId));
    }

    public static int getFailureCountDelta(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        return null == executorIdAndTaskIdKeyToFailureCountDeltaMap.get(taskIdAndExecutorIdKey) ? 0 : executorIdAndTaskIdKeyToFailureCountDeltaMap.get(taskIdAndExecutorIdKey).get();
    }

    /**
     * 重置analyse统计信息. servers底下的success/failure不清零。
     *
     * @param taskId
     * @param executorId
     */
    public static void resetTotalCountDeltaAndFailureCountDelta(final String taskId, final String executorId) {
        String taskIdAndExecutorIdKey = buildTaskIdAndExecutorIdKey(taskId, executorId);
        if (executorIdAndTaskIdKeyToTotalCountDeltaMap.containsKey(taskIdAndExecutorIdKey)) {
            executorIdAndTaskIdKeyToTotalCountDeltaMap.get(taskIdAndExecutorIdKey).set(0);
        }
        if (executorIdAndTaskIdKeyToFailureCountDeltaMap.containsKey(taskIdAndExecutorIdKey)) {
            executorIdAndTaskIdKeyToFailureCountDeltaMap.get(taskIdAndExecutorIdKey).set(0);
        }
    }


}
